﻿#region 文件信息

/*----------------------------------------------------------------
//
// 文件名称：
// 文件功能描述：
// 设计要求：
//
// 文 件 名：    SyntaxUtils
// 创建者：      杨程
// 创建日期：	    2023/2/4 21:56:45

//----------------------------------------------------------------*/

#endregion

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Vampirewal.Admin.SourceGenerator.Tools;

public class SyntaxUtils
{
    public static bool HasModifier(MemberDeclarationSyntax syntax, params SyntaxKind[] modifiers)
    {
        return syntax.Modifiers.Any(m => modifiers.Contains(m.Kind()));
    }

    public static bool HasModifiers(MemberDeclarationSyntax syntax, params SyntaxKind[] modifiers)
    {
        var syntaxKinds = syntax.Modifiers.Select(n => n.Kind()).ToList();
        return modifiers.All(m => syntaxKinds.Contains(m));
    }

    public static string GetName(SyntaxNode syntaxNode)
    {
        switch (syntaxNode)
        {
            case BaseTypeDeclarationSyntax baseTypeDeclarationSyntax:
                return baseTypeDeclarationSyntax.Identifier.Text;

            case BaseNamespaceDeclarationSyntax baseNamespaceDeclarationSyntax:
                return baseNamespaceDeclarationSyntax.Name.ToString();

            case VariableDeclaratorSyntax variableDeclaratorSyntax:
                return variableDeclaratorSyntax.Identifier.Text;

            case NameEqualsSyntax nameEqualsSyntax:
                return nameEqualsSyntax.Name.Identifier.Text;

            default:
                throw new NotImplementedException();
        }
    }

    public static bool HasAttribute(MemberDeclarationSyntax classDeclaration, Func<string, bool> func)
    {
        return GetAttribute(classDeclaration, func) != null;
    }

    public static bool HasAttribute(MemberDeclarationSyntax classDeclaration, string AttributeName)
    {
        var dto = GetAttribute(classDeclaration, AttributeName);

        return dto != null;
    }

    public static AttributeSyntax GetAttribute(MemberDeclarationSyntax classDeclaration, Func<string, bool> func)
    {
        return classDeclaration.AttributeLists.SelectMany(m => m.Attributes)
            .FirstOrDefault(m => func(m.Name.ToString()));
    }

    public static AttributeSyntax GetAttribute(MemberDeclarationSyntax classDeclaration, string AttributeName)
    {
        var attributes = classDeclaration.AttributeLists.SelectMany(m => m.Attributes);

        var attr = attributes.FirstOrDefault(m =>
        {
            var nameSyntax = m.Name as IdentifierNameSyntax;
            if (nameSyntax.Identifier.Text.Equals(AttributeName))
            {
                return true;
            }
            return false;
        });

        return attr;
    }

    /// <summary>
    /// 检查是否包含AOP特性
    /// </summary>
    /// <param name="classDeclaration"></param>
    /// <returns></returns>
    public static bool HasAopAttribute(MemberDeclarationSyntax classDeclaration, out AttributeSyntax attribute)
    {
        attribute = GetAopAttribute(classDeclaration);

        return attribute != null;
    }

    /// <summary>
    /// 获取已AOP结尾的特性
    /// </summary>
    /// <param name="classDeclaration"></param>
    /// <returns></returns>
    public static AttributeSyntax GetAopAttribute(MemberDeclarationSyntax classDeclaration)
    {
        var attributes = classDeclaration.AttributeLists.SelectMany(m => m.Attributes);

        var attr = attributes.FirstOrDefault(m =>
        {
            var nameSyntax = m.Name as IdentifierNameSyntax;
            if (nameSyntax.Identifier.ValueText.EndsWith("AOP"))
            {
                return true;
            }
            return false;
        });

        return attr;
    }

    public static List<string> GetUsings(ClassDeclarationSyntax classDeclarationSyntax)
    {
        var compilationUnitSyntax = classDeclarationSyntax.SyntaxTree.GetRoot() as CompilationUnitSyntax;
        var usings = compilationUnitSyntax.Usings.Select(m => m.ToString()).ToList();
        return usings;
    }
}